﻿using HarmonyLib;
using System.Collections.Generic;
using System.Linq;

namespace Duplicant_Reacharound_Expanded
{
    public class Patches
    {
       private static readonly CellOffset[][] TableExpansion = new CellOffset[20][]
       {
          new CellOffset[4]
          {
            Patches.O(0, -4),
            Patches.O(0, -3),
            Patches.O(0, -2),
            Patches.O(0, -1)
          },
          new CellOffset[5]
          {
            Patches.O(1, -4),
            Patches.O(1, 0),
            Patches.O(1, -1),
            Patches.O(1, -2),
            Patches.O(1, -3)
          },
          new CellOffset[5]
          {
            Patches.O(1, -4),
            Patches.O(0, -1),
            Patches.O(0, -2),
            Patches.O(0, -3),
            Patches.O(0, -4)
          },
          new CellOffset[6]
          {
            Patches.O(2, -4),
            Patches.O(1, 0),
            Patches.O(1, -1),
            Patches.O(1, -2),
            Patches.O(1, -3),
            Patches.O(2, -3)
          },
          new CellOffset[6]
          {
            Patches.O(3, -3),
            Patches.O(1, 0),
            Patches.O(1, -1),
            Patches.O(1, -2),
            Patches.O(2, -2),
            Patches.O(2, -3)
          },
          new CellOffset[5]
          {
            Patches.O(3, -2),
            Patches.O(1, 0),
            Patches.O(1, -1),
            Patches.O(2, -1),
            Patches.O(2, -2)
          },
          new CellOffset[4]
          {
            Patches.O(3, -1),
            Patches.O(1, 0),
            Patches.O(2, 0),
            Patches.O(3, 0)
          },
          new CellOffset[4]
          {
            Patches.O(3, -1),
            Patches.O(1, 0),
            Patches.O(2, 0),
            Patches.O(2, -1)
          },
          new CellOffset[3]
          {
            Patches.O(3, 0),
            Patches.O(1, 0),
            Patches.O(2, 0)
          },
          new CellOffset[5]
          {
            Patches.O(1, 4),
            Patches.O(1, 0),
            Patches.O(1, 1),
            Patches.O(1, 2),
            Patches.O(1, 3)
          },
          new CellOffset[5]
          {
            Patches.O(1, 4),
            Patches.O(0, 1),
            Patches.O(0, 2),
            Patches.O(0, 3),
            Patches.O(0, 4)
          },
          new CellOffset[6]
          {
            Patches.O(2, 4),
            Patches.O(1, 0),
            Patches.O(1, 1),
            Patches.O(1, 2),
            Patches.O(1, 3),
            Patches.O(2, 3)
          },
          new CellOffset[6]
          {
            Patches.O(3, 3),
            Patches.O(1, 0),
            Patches.O(1, 1),
            Patches.O(1, 2),
            Patches.O(2, 2),
            Patches.O(2, 3)
          },
          new CellOffset[5]
          {
            Patches.O(3, 2),
            Patches.O(1, 0),
            Patches.O(1, 1),
            Patches.O(2, 1),
            Patches.O(2, 2)
          },
          new CellOffset[4]
          {
            Patches.O(3, 1),
            Patches.O(1, 0),
            Patches.O(2, 0),
            Patches.O(3, 0)
          },
          new CellOffset[4]
          {
            Patches.O(3, 1),
            Patches.O(1, 0),
            Patches.O(2, 0),
            Patches.O(2, 1)
          },
          new CellOffset[4]
          {
            Patches.O(3, 0),
            Patches.O(1, 0),
            Patches.O(2, 0),
            Patches.O(3, 0)
          },
          new CellOffset[4]
          {
            Patches.O(0, 4),
            Patches.O(0, 3),
            Patches.O(0, 2),
            Patches.O(0, 1)
          },
          new CellOffset[5]
          {
            Patches.O(0, 5),
            Patches.O(0, 1),
            Patches.O(0, 2),
            Patches.O(0, 3),
            Patches.O(0, 4)
          },
          new CellOffset[6]
          {
            Patches.O(1, 5),
            Patches.O(0, 1),
            Patches.O(0, 2),
            Patches.O(0, 3),
            Patches.O(0, 4),
            Patches.O(0, 5)
          }
        };
        private static bool OffsetsExpanded = false;
        public static bool SHOULDSHRINK = false;

        private static CellOffset O(int x, int y) => new CellOffset(x, y);

        [HarmonyPatch(typeof(Game), "OnPrefabInit")]
        public static class GamePatch
        {
            public static void Postfix() => Patches.GamePatch.ExpandTables();

            public static void ExpandTables()
            {
                if (Patches.OffsetsExpanded)
                    return;
                Patches.GamePatch.ExpandTable(ref OffsetGroups.InvertedStandardTable);
                Patches.GamePatch.ExpandTable(ref OffsetGroups.InvertedStandardTableWithCorners);
                Patches.OffsetsExpanded = true;
            }

            public static void ExpandTable(ref CellOffset[][] inputTable)
            {
                CellOffset[][] cellOffsetArray = OffsetTable.Mirror(((IEnumerable<CellOffset[]>)inputTable).ToList<CellOffset[]>().Concat<CellOffset[]>((IEnumerable<CellOffset[]>)Patches.TableExpansion).ToArray<CellOffset[]>());
                inputTable = cellOffsetArray;
            }

            public static bool Equals(CellOffset[] a, CellOffset[] b)
            {
                if (a == null || b == null || a.Length != b.Length || a.Length == 0)
                    return false;
                for (int index = 0; index < a.Length; ++index)
                {
                    if (!a[index].Equals(b[index]))
                        return false;
                }
                return true;
            }

            public static bool Contains(CellOffset[][] table, CellOffset[] array)
            {
                foreach (CellOffset[] a in table)
                {
                    if (Patches.GamePatch.Equals(a, array))
                        return true;
                }
                return false;
            }
        }
    }
}
